/* Copyright (c) 2009-2010, Sean A.O. Harney <sharney3@gmail.com> */

#include "omf.h"


// //set _len=0 or stdin_ar=NULL for no stdin
// stdin is raw binary stream, not \0 terminated!
// Argument argv elements \0 terminateda and final element should be NULL
bool command_launch(LLIST_P argvlist, uint8_t * stdin_ar, size_t stdin_len)
{

    int pipe_fds[2];
    pid_t pid;

    if (stdin_len > 0 && stdin_ar != NULL)
      {
	  if (pipe(pipe_fds) == -1)
	    {
		perror("pipe()");
		return false;
	    }
      }
    pid = fork();
    switch (pid)
      {
      case -1:
	  perror("command_launch():fork()");

	  if (stdin_len > 0 && stdin_ar != NULL)
	    {
		close(pipe_fds[0]);
		close(pipe_fds[1]);
	    }
	  return false;
      case 0:			/* child process */
	  debug1_printf("command child process: %d\n", getpid());

	  if (stdin_len > 0 && stdin_ar != NULL)
	    {
		close(pipe_fds[1]);	//close write end

		//stdin data may be coming from the pipe, may not sendanything but dup always anyway.
		dup2(pipe_fds[0], fileno(stdin));	// pipe read end to stdin
	    }

	  int argc;
	  char *argv[MAX_COMMAND_ARGV];
	  LLIST_P walker;

	  for (argc = 0, walker = argvlist;
	       walker != NULL && argc < MAX_COMMAND_ARGV - 1;
	       walker = walker->next)
	    {
		argv[argc] = walker->element;
		argc++;
	    }

	  argv[argc] = NULL;	//as execv is expecting


	  outputlog_command_chldlog_init(argv[0], stdin_ar, stdin_len,
					 argc, (uint8_t **) argv);
	  execv(argv[0], argv);
	  /* if it got here it failed */
	  fatal_error_perror("execv()");	/* end child_process */
	  exit(EXIT_FAILURE);	/* end child process */
      default:			/* parent process (pipe reader) */
	  glob.current_target_processes++;
	  if (stdin_len > 0 && stdin_ar != NULL)
	    {
		close(pipe_fds[0]);	//close read end
		write(pipe_fds[1], stdin_ar, stdin_len);	//todo:error check
		close(pipe_fds[1]);	//close write end
	    }
	  return true;
      }
}
